﻿/*------------------------------------------------------------------------

SMART_PTR.HPP v3.3

Copyright 楊志賢 CxxlMan, 2008 - 2013
All Rights Reserved


------------------------------------------------------------------------*/

#if !defined(__SMART_PTR_HPP_CxxlMan)
#define __SMART_PTR_HPP_CxxlMan

#include "DLLDEF.HPP"
#include "CXXLOBJECT.HPP"

#if defined(_CXXLOBJECT_DLLEXPORT)
#define CXXLOBJECT_DLLEXPORT CXXL_DLLEXPORT
#else
#define CXXLOBJECT_DLLEXPORT CXXL_DLLIMPORT
#endif


namespace CxxlMan
{

template<typename T> class Smart_Array_Package;

class CXXLOBJECT_DLLEXPORT Smart_Ptr_Base
{

  // 用來串連 "和自己一樣，包裝同一個物件" 的所有智慧指標的串列
  Smart_Ptr_Base *Prev;
  Smart_Ptr_Base *Next;

  // 把包裹的 cxxlObject 記錄無條件清為 NULL
  // 由 cxxlObject 叫用
  virtual void cxxlFASTCALL ClearObjToNULL() = 0;

  cxxlObject *m_Host; // 擁有此智慧指標的物件(父物件)
  void cxxlFASTCALL ResetHost(cxxlObject *newHost)
  {
    m_Host = newHost;
  }

protected:
  // Constructor
  Smart_Ptr_Base(cxxlObject *pObj,cxxlObject *Host);
  virtual ~Smart_Ptr_Base(){};  // Destructor

  void cxxlFASTCALL Attach(cxxlObject *Obj);
  void cxxlFASTCALL Release(cxxlObject *Obj);

public:

  friend class cxxlObject;
  template<typename T> friend class Smart_Array_Package;
};

template <typename T>
class Smart_Ptr:public Smart_Ptr_Base
{
  T *m_pobj;

  void cxxlFASTCALL ClearObjToNULL()
  {
    m_pobj = NULL;
  }

public:
  // Destructor
  virtual ~Smart_Ptr()
  {
    // Release(m_pobj);
    Release((cxxlObject*)(const cxxlObject*)m_pobj);
  }

  // Constructor
  Smart_Ptr(T *pcxxlObj,cxxlObject *Host = rootObject)
    //:Smart_Ptr_Base(pcxxlObj,Host)
    :Smart_Ptr_Base((cxxlObject*)(const cxxlObject*)pcxxlObj,Host) // 為了能包裹 const 物件
  {
    m_pobj = pcxxlObj;
  }

  // Copy Constructor
  Smart_Ptr(const Smart_Ptr<T> &Src,cxxlObject *Host = rootObject)
    //:Smart_Ptr_Base((T *)Src,Host)
    :Smart_Ptr_Base((cxxlObject*)(const cxxlObject*)(T *)Src,Host) // 為了能包裹 const 物件
  {
    m_pobj = (T *)Src;
  }

  // 設定函數
  Smart_Ptr<T> & cxxlFASTCALL operator=(T *pcxxlObj)
  {
    if(pcxxlObj == m_pobj) // 防止自己複製給自己意外刪掉
      Smart_Ptr<T> tmp(pcxxlObj);
    // Release(m_pobj);
    Release((cxxlObject*)(const cxxlObject*)m_pobj); // 為了能包裹 const 物件
    // Attach(pcxxlObj);
    Attach((cxxlObject*)(const cxxlObject*)pcxxlObj); // 為了能包裹 const 物件
    m_pobj = pcxxlObj;
    return *this;
  }

  // 拷備函數
  virtual Smart_Ptr<T> & cxxlFASTCALL operator=(const Smart_Ptr<T> &Src)
  {
    *this = (T*)Src; // 叫用設定函數
    return *this;
  }


  // 檢查包裹的物件是不是 NULL(未包裹物件)
  bool cxxlFASTCALL isNULL() const
  {
    return m_pobj == NULL;
  }

  // 放棄持有的物件(包裹的物件成為 NULL)
  void cxxlFASTCALL Destroy()
  {
    Release(m_pobj);
    m_pobj = NULL;
  }

  // 可用像 ObjPtr-> 的方式使用包裹的物件
  T *cxxlFASTCALL operator->() const
  {
    return m_pobj;
  }

  // 用自動轉形方式取得包裹的物件
  cxxlFASTCALL operator T*() const
  {
    return m_pobj;
  }

};


/*
  轉形函數
*/
template <class L,class K>
Smart_Ptr<L> cxxlFASTCALL Smart_Cast(const Smart_Ptr<K> &Src,cxxlObject *Host=rootObject)
{
  L *temp = dynamic_cast<L *>((K*)Src);

  return Smart_Ptr<L>(temp,Host);
}


}   /* namespace CxxlMan */
#endif

